import { useEffect, useState } from 'react';
import { useModel } from 'umi';

import * as apiAreaFilter from '@/services/areaFilter';
import {
  AreaGroup,
  DefaultOptionAll,
  DefaultOptionEmpty,
  getVpnGroupTypeText,
  GroupDisplayAreaFilterPolicy,
  Langs,
} from '@/services/consts';
import * as apiData from '@/services/data';
import * as apiDeployConfig from '@/services/deployConfig';
import * as apiGeoip from '@/services/geoip';
import * as apiProduct from '@/services/product';
import * as apiSupplier from '@/services/serverSupplier';
import * as apiTag from '@/services/tag';
import * as apiTicketType from '@/services/ticketType';
import * as apiGroup from '@/services/vpnGroup';
import * as apiCdnDomain from '@/services/cdnDomain';

const DEFAULT_PRODUCT_ID = 1001;

export default function useGlobalModel() {
  const [deployConfigPublish, setDeployConfigPublish] =
    useState<boolean>(false);
  const [nextProductId, setNextProductId] =
    useState<number>(DEFAULT_PRODUCT_ID);
  const [products, setProducts] = useState<API.Product[]>([]);
  const [productMenuItems, setProductMenuItems] = useState<any[]>([]);
  const [productTabItems, setProductTabItems] = useState<any[]>([]);
  const [productOptions, setProductOptions] = useState<any[]>([]);
  const [suppliers, setSuppliers] = useState<API.ServerSupplierModel[]>([]);
  const [supplierOptions, setSupplierOptions] = useState<any[]>([]);
  const [ticketTypeTrees, setTicketTypeTrees] = useState<API.TreeSelectItem[]>(
    [],
  );
  const [tags, setTags] = useState<API.TagModel[]>([]);
  const [vpnGroupTrees, setVpnGroupTrees] = useState<API.TreeSelectItem[]>([]);

  const [areaFilters, setAreaFilters] = useState<API.AreaFilter[]>([]);
  const [areaFilterOptions, setAreaFilterOptions] = useState<any[]>([]);
  const [globalGrafanaModel, setGlobalGrafanaModel] =
    useState<API.GrafanaModel>(undefined);
  const [geoipIsps, setGeoipIsps] = useState<API.GeoipIsp[]>([]);
  const [deployConfigs, setDeployConfigs] = useState<API.DeployConfig[]>([]);
  const [cdnAccounts, setCdnAccounts] = useState<API.CdnAccount[]>([]);
  const [cdnDomains, setCdnDomains] = useState<API.CdnDomain[]>([]);

  const { initialState } = useModel('@@initialState');

  useEffect(() => {
    if (initialState && initialState.currentUser) {
      reloadDatas();
    }
  }, [initialState]);

  const reloadDatas = async () => {
    await reloadProducts();
    await reloadTags();
    await reloadVpnGroupTrees();
    await reloadServerSuppliers();
    await reloadTicketTypeTrees();
    await reloadAreaFilters();
    await reloadGrafana();
    await reloadGeoipIsps();
    await reloadDeployConfigs();
    await reloadCdnAccounts();
    await reloadCdnDomains();
  };

  const reloadGrafana = async () => {
    const result = await apiData.getGrafana();
    if (result && result.success === true) {
      const { data } = result;
      setGlobalGrafanaModel(data);
    }
  };

  const reloadProducts = async () => {
    const result = await apiProduct.all();

    if (result && result.success === true) {
      const { data } = result;

      setProducts(data);

      let menuItems: any[] = [];
      let options: any[] = [];
      let tabItems: any[] = [];

      if (data && data.length > 0) {
        const nextProductId = data[data.length - 1].id + 1;
        setNextProductId(nextProductId);

        for (let item of data) {
          menuItems.push({
            label: item.name,
            key: item.id.toString(),
            disabled: !item.status,
          });

          options.push({
            label: item.name,
            value: item.id,
            disabled: !item.status,
          });

          tabItems.push({
            tab: item.name,
            key: item.id.toString(),
            disabled: !item.status,
          });
        }
      }

      setProductMenuItems(menuItems);
      setProductOptions(options);
      setProductTabItems(tabItems);
    }
  };

  const getProductMenuItems = (hasAll: boolean) => {
    let menuItems: any[] = productMenuItems.slice();
    if (hasAll === true && menuItems.length > 0) {
      menuItems?.unshift({
        label: DefaultOptionAll.label,
        key: DefaultOptionAll.key,
        disabled: false,
      });
    }

    return menuItems;
  };

  const getProductTagItems = (hasAll: boolean) => {
    let menuItems: any[] = productTabItems.slice();
    if (hasAll === true && menuItems.length > 0) {
      menuItems?.unshift({
        tab: DefaultOptionAll.label,
        key: '',
        disabled: false,
      });
    }

    return menuItems;
  };

  const getProductOptions = (hasEmpty: boolean) => {
    let options: any[] = productOptions.slice();
    if (hasEmpty === true && options.length > 0) {
      options?.unshift({
        label: DefaultOptionAll.label,
        value: DefaultOptionAll.value,
        disabled: false,
      });
    }

    return options;
  };

  const getProduct = (id: number) => {
    if (!id || id == 0) {
      return undefined;
    }
    for (let item of products) {
      if (item.id === id) {
        return item;
      }
    }

    return undefined;
  };

  const getProductLangs = (productId: number) => {
    let langs = [];
    const product = getProduct(productId);
    if (product && product.langs && product.langs.length > 0) {
      for (let item of Langs) {
        if (product.langs!.indexOf(item.value) !== -1) {
          langs.push(item);
        }
      }
    }

    return langs;
  };

  const getProductsLangs = (productIds: number[]) => {
    let langs = [];
    let keys = [];
    for (let i = 0; i < productIds.length; i++) {
      let productId = productIds[i];
      const product = getProduct(productId);
      if (product && product.langs && product.langs.length > 0) {
        for (let item of Langs) {
          if (
            product.langs!.indexOf(item.value) !== -1 &&
            keys.indexOf(item.value) === -1
          ) {
            keys.push(item.value);
            langs.push(item);
          }
        }
      }
    }

    return langs;
  };

  const getProductsNames = (productIds: number[]) => {
    let names = [];
    for (let i = 0; i < productIds.length; i++) {
      let productId = productIds[i];
      const product = getProduct(productId);
      if (product) {
        names.push(product.name);
      }
    }

    return names;
  };

  const reloadTags = async () => {
    const result = await apiTag.all();
    if (result && result.success === true) {
      const { data } = result;
      setTags(data);
    }
  };

  const getTags = (types?: string[], productId?: number) => {
    let destTags = [];
    for (let item of tags) {
      if (matchTag(item, types, productId)) {
        destTags.push(item);
      }
    }

    return destTags;
  };

  const getTag = (id?: string) => {
    if (!id) return undefined;

    for (let item of tags) {
      if (item.id == id) {
        return item;
      }
    }

    return undefined;
  };

  const matchTag = (
    tag: API.TagModel,
    types?: string[],
    productId?: number,
  ) => {
    if (productId && productId > 0 && tag.productId !== productId) {
      return false;
    }
    if (!types || types?.indexOf(tag.type) == -1) {
      return false;
    }
    return true;
  };

  const reloadVpnGroupTrees = async () => {
    const treeData = await apiGroup.loadGroupTrees({});
    setVpnGroupTrees(treeData);
  };

  const getVpnGroupTrees = () => {
    return vpnGroupTrees;
  };

  const getVpnGroupExTrees = (
    productId: string | undefined,
    displayRemark: boolean | undefined = undefined,
  ) => {
    // console.log(displayRemark);
    const treeData = getProductVpnGroupTrees(productId);
    let nodes: API.TreeSelectItem[] = [];
    if (treeData && treeData.length > 0) {
      treeData.sort((a, b) => {
        return (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0);
      });
      for (let td of treeData) {
        td.children.sort((a, b) => {
          return (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0);
        });
      }

      for (let td of treeData) {
        // console.log(td);
        let node: API.TreeSelectItem = {
          // title: `[${getProductsNames(
          //   td.refData?.productIds,
          // )}] [${getVpnGroupTypeText(td.refData?.type)}] ${td.title} ${displayRemark == true && td.refData?.remark
          //   ? `　　　[${td.refData.remark.length > 20 ? `${td.refData.remark.substring(0, 30)} ...` : td.refData.remark}]` : ''}`,

          title: `${td.refData?.sort} [${getVpnGroupTypeText(
            td.refData?.type,
          )}] ${td.title} ${
            displayRemark == true && td.refData?.remark
              ? `　　　[${
                  td.refData.remark.length > 20
                    ? `${td.refData.remark.substring(0, 30)} ...`
                    : td.refData.remark
                }]`
              : ''
          }`,

          value: td.value,
          children: [],
          refData: td.refData,
        };
        if (td.disabled != true) {
          node.title = `✔ ${node.title}`;
        } else {
          node.title = `✖ ${node.title}`;
        }
        for (let ctd of td.children) {
          if (ctd.disabled != true) {
            node.children.push({
              title: `✔ ${ctd.title}`,
              value: ctd.value,
              children: [],
              refData: ctd.refData,
            });
          } else {
            node.children.push({
              title: `✖ ${ctd.title}`,
              value: ctd.value,
              children: [],
              refData: ctd.refData,
            });
          }
        }
        nodes.push(node);
      }
    }
    return nodes;
  };

  const getVpnGroupOptions = (productId: string | undefined) => {
    // console.log(displayRemark);
    const treeData = getProductVpnGroupTrees(productId);
    // console.log(treeData);
    let nodes = [];
    if (treeData && treeData.length > 0) {
      treeData.sort((a, b) => {
        return (a.disabled ? 1 : 0) - (b.disabled ? 1 : 0);
      });

      for (let td of treeData) {
        let node = {
          label: `${td.title}`,
          value: td.value,
        };
        // if (td.disabled != true) {
        //   node.label = `✔ ${node.label}`;
        // } else {
        //   node.label = `✖ ${node.label}`;
        // }
        nodes.push(node);
      }
    }
    return nodes;
  };

  const getProductVpnGroupTrees = (productId: string | undefined) => {
    if (!productId || productId == undefined) {
      return vpnGroupTrees;
    }

    // for (let item of vpnGroupTrees) {
    //   if (item.value == `product_${productId}`) {
    //     return [item];
    //   }
    // }
    // return [];

    // let xx = [2001, 2002];
    // console.log('test:', xx.indexOf(2002));

    // for (let i = 0; i < vpnGroupTrees.length; i++) {
    //   let item = vpnGroupTrees[i];
    //   console.log(
    //     item.refData.productIds,
    //     productId,
    //     item.refData.productIds.indexOf(productId),
    //   );
    // }

    let list = vpnGroupTrees.filter((item) => {
      return (
        item.refData != null &&
        item.refData.productIds.indexOf(parseInt(productId)) != -1
      );
    });

    return list;
  };

  const getVpnGroupTitle = (groupIds: string[] | undefined) => {
    if (!groupIds || groupIds == undefined) {
      return '';
    }
    let names: string[] = [];
    for (let id of groupIds) {
      for (let item of vpnGroupTrees) {
        if (item.value == id) {
          names.push(item.title);
        } else {
          for (let child of item.children) {
            if (child.value == id) {
              names.push(child.title);
            }
          }
        }
      }
    }

    return names.join(',');
  };

  const getVpnGroupList = () => {
    let options: API.VpnGroupModel[] = [];
    for (let d of vpnGroupTrees) {
      options.push(d.refData);
    }

    return options;
  };

  const reloadServerSuppliers = async () => {
    const result = await apiSupplier.all();

    if (result && result.success === true) {
      const { data } = result;

      setSuppliers(data);

      let options: any[] = [];

      if (data && data.length > 0) {
        for (let item of data) {
          options.push({
            label: item.name,
            value: item.id,
            disabled: !item.status,
          });
        }
      }

      setSupplierOptions(options);
    }
  };

  const getSupplier = (id: number | undefined) => {
    if (!id || id == 0) {
      return undefined;
    }
    for (let item of suppliers) {
      if (item.id === id) {
        return item;
      }
    }

    return undefined;
  };

  const reloadTicketTypeTrees = async () => {
    const result = await apiTicketType.loadTicketTypeTrees();
    setTicketTypeTrees(result);
  };

  const getTicketTypeTrees = () => {
    return ticketTypeTrees;
  };

  const reloadAreaFilters = async () => {
    const result = await apiAreaFilter.all();

    if (result && result.success === true) {
      const { data } = result;

      setAreaFilters(data);

      let options: any[] = [];

      if (data && data.length > 0) {
        for (let item of data) {
          options.push({
            label: item.name,
            value: item.id,
            disabled: !item.status,
          });
        }
      }

      setAreaFilterOptions(options);
    }
  };

  const getAreaFilterOptions = (hasEmpty: boolean) => {
    let options: any[] = areaFilterOptions.slice();
    if (hasEmpty === true && options.length > 0) {
      options?.unshift({
        label: DefaultOptionEmpty.label,
        value: DefaultOptionEmpty.value,
        disabled: false,
      });
    }

    return options;
  };

  const getAreaFilter = (id: string) => {
    if (!id || id == '') {
      return undefined;
    }
    for (let item of areaFilters) {
      if (item.id === id) {
        return item;
      }
    }

    return undefined;
  };

  const getGroupAreaFilterPolicyText = (policy?: API.VpnGroupPolicy) => {
    if (
      policy &&
      policy.displayAreaFilterPolicy &&
      policy.displayAreaFilterPolicy != '' &&
      policy.displayAreaFilterPolicyAreaFilterIds &&
      policy.displayAreaFilterPolicyAreaFilterIds.length > 0
    ) {
      let text = '';
      if (
        policy.displayAreaFilterPolicy ==
        GroupDisplayAreaFilterPolicy.Display.value
      ) {
        text = '显示';
      } else if (
        policy.displayAreaFilterPolicy ==
        GroupDisplayAreaFilterPolicy.Hidden.value
      ) {
        text = '隐藏';
      }

      let fullAreas = [];

      for (
        let i = 0;
        i < policy.displayAreaFilterPolicyAreaFilterIds.length;
        i++
      ) {
        let id = policy.displayAreaFilterPolicyAreaFilterIds[i];

        let areaFilter = getAreaFilter(id);

        //console.log('policy.areaFilter: ', areaFilter);

        if (areaFilter != null) {
          let areas =
            areaFilter.areaGroup == AreaGroup.Foreign.value
              ? areaFilter.areas
              : areaFilter.areaGroup;

          fullAreas.push(areas);
        }
      }

      if (fullAreas.length > 0) {
        return `${text}: ${fullAreas.join(',')}`;
      }
    }
    return null;
  };

  const reloadGeoipIsps = async () => {
    const result = await apiGeoip.ispall();

    if (result && result.success === true) {
      const { data } = result;
      setGeoipIsps(data);
    }
  };
  const getGeoipIspOptions = () => {
    let options: any[] = [];
    if (geoipIsps) {
      for (let item of geoipIsps) {
        options.push({
          label: item.name,
          value: item.id,
        });
      }
    }
    return options;
  };
  const getGeoipIspNameOptions = () => {
    let options: any[] = [];
    if (geoipIsps) {
      for (let item of geoipIsps) {
        options.push({
          label: item.name,
          value: item.name,
        });
      }
    }
    return options;
  };
  const getGeoipIsp = (id: string) => {
    if (geoipIsps) {
      for (let item of geoipIsps) {
        if (item.id == id) return item;
      }
    }
    return undefined;
  };

  const reloadDeployConfigs = async () => {
    const result = await apiDeployConfig.all();

    if (result && result.success === true) {
      const { data } = result;

      setDeployConfigs(data);
    }
  };
  const getDeployConfigOptions = (type: number) => {
    let options: any[] = [];
    if (deployConfigs) {
      for (let item of deployConfigs) {
        if (item.type != type) continue;
        options.push({
          label: item.name,
          value: item.id,
          disabled: !item.status,
        });
      }
    }

    return options;
  };

  const reloadCdnAccounts = async () => {
    const result = await apiCdnDomain.all();

    if (result && result.success === true) {
      const { data } = result;

      setCdnAccounts(data);
    }
  };
  const getCdnAccountOptions = (type?: number) => {
    let options: any[] = [];
    if (cdnAccounts) {
      for (let item of cdnAccounts) {
        if(type && item.type != type) continue;
        options.push({
          label: item.name,
          value: item.id,
        });
      }
    }
    return options;
  };
  const reloadCdnDomains = async () => {
    const result = await apiCdnDomain.cdnDomainAll();

    if (result && result.success === true) {
      const { data } = result;

      setCdnDomains(data);
    }
  };
  const getCdnDomainOptions = (cdnAccountId?: string) => {
    let options: any[] = [];
    if (cdnDomains) {
      for (let item of cdnDomains) {
        if(cdnAccountId && item.cdnAccountId != cdnAccountId) continue;
        options.push({
          label: item.name,
          value: item.id,
          disabled: !item.status,
        });
      }
    }

    return options;
  };

  return {
    deployConfigPublish,
    setDeployConfigPublish,

    nextProductId,
    productOptions,
    reloadProducts,
    getProduct,
    getProductMenuItems,
    getProductTagItems,
    getProductOptions,
    getProductLangs,
    getProductsLangs,
    getProductsNames,
    reloadTags,
    getTags,
    getTag,
    tags,
    reloadVpnGroupTrees,
    getVpnGroupTrees,
    getProductVpnGroupTrees,
    getVpnGroupTitle,
    getVpnGroupExTrees,
    getVpnGroupOptions,
    getVpnGroupList,
    reloadServerSuppliers,
    suppliers,
    supplierOptions,
    getSupplier,
    reloadAreaFilters,
    getAreaFilterOptions,
    getAreaFilter,
    getGroupAreaFilterPolicyText,

    globalGrafanaModel,
    reloadGeoipIsps,
    getGeoipIspOptions,
    getGeoipIspNameOptions,
    getGeoipIsp,

    reloadCdnAccounts,
    reloadCdnDomains,
    getCdnAccountOptions,
    getCdnDomainOptions,
    cdnDomains,
    reloadDeployConfigs,
    deployConfigs,
    getDeployConfigOptions,
    reloadTicketTypeTrees,
    getTicketTypeTrees,
    // getTicketParentType,
    // getTicketType,
  };
}
